package com.share.domain.strategy.service;

import com.share.domain.strategy.model.entity.RaffleAwardEntity;
import com.share.domain.strategy.model.entity.RaffleFactorEntity;
import com.share.domain.strategy.model.entity.StrategyAwardEntity;
import com.share.domain.strategy.repository.IStrategyRepository;
import com.share.domain.strategy.service.armory.IStrategyDispatch;
import com.share.domain.strategy.service.rule.chain.factory.DefaultChainFactory;
import com.share.domain.strategy.service.rule.tree.factory.DefaultTreeFactory;
import com.share.types.enums.ResponseCode;
import com.share.types.exception.AppException;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;

/**
 * 抽奖策略抽象类
 */
@Slf4j
public abstract  class AbstractRaffleStrategy implements IRaffleStrategy {
    protected IStrategyRepository repository;
    protected IStrategyDispatch strategyDispatch;

    protected final DefaultChainFactory defaultChainFactory;

    protected final DefaultTreeFactory defaultTreeFactory;

    public AbstractRaffleStrategy(IStrategyRepository repository, IStrategyDispatch strategyDispatch, DefaultChainFactory defaultChainFactory, DefaultTreeFactory defaultTreeFactory){
        this.repository = repository;
        this.strategyDispatch = strategyDispatch;
        this.defaultChainFactory=defaultChainFactory;
        this.defaultTreeFactory = defaultTreeFactory;
    }
    @Override
    public RaffleAwardEntity performRaffle(RaffleFactorEntity raffleFactorEntity) {
        //参数校验
        String userId = raffleFactorEntity.getUserId();
        Long strategyId = raffleFactorEntity.getStrategyId();
        if(null==userId||null==strategyId){
            throw new AppException(ResponseCode.ILLEGAL_PARAMETER.getCode(),ResponseCode.ILLEGAL_PARAMETER.getInfo());
        }

        //责任链抽奖【拿到最初的奖品id，之后需根据id处理抽奖】 黑名单、权重等非默认抽奖直接返回抽奖结果
        DefaultChainFactory.StrategyAwardVo chainStrategyAwardVo = raffleLogicChain(userId, strategyId);
        log.info("抽奖策略计算-责任链 userId:{};strategyId:{};awardId:{};logicModel:{}",userId,strategyId,chainStrategyAwardVo.getAwardId(),chainStrategyAwardVo.getLogicModel());

        //如果非默认链 只会抽到的奖品
        if(!DefaultChainFactory.LogicModel.RULE_DEFAULT.getCode().equals(chainStrategyAwardVo.getLogicModel()))
        {
            return buildRaffleAwardEntity(strategyId, chainStrategyAwardVo.getAwardId(), chainStrategyAwardVo.getAwardRuleValue());
        }

        DefaultTreeFactory.StrategyAwardVo treeStrategyAwardVo = raffleLogicTree(userId,strategyId,chainStrategyAwardVo.getAwardId(),raffleFactorEntity.getEndDateTime());
        log.info("抽奖策略计算-决策链 userId:{};strategyId:{};awardId:{};ruleValue:{}",userId,strategyId,treeStrategyAwardVo.getAwardId(),treeStrategyAwardVo.getAwardRuleValue());
        return buildRaffleAwardEntity(strategyId,treeStrategyAwardVo.getAwardId(),treeStrategyAwardVo.getAwardRuleValue());
    }

    protected abstract DefaultTreeFactory.StrategyAwardVo raffleLogicTree(String userId, Long strategyId, Integer awardId, Date endDateTime);

    private RaffleAwardEntity buildRaffleAwardEntity(Long strategyId,Integer awardId,String awardConfig){
        StrategyAwardEntity strategyAward = repository.queryStrategyAwardEntity(strategyId,awardId);
        return RaffleAwardEntity.builder()
                .awardId(awardId)
                .awardConfig(awardConfig)
                .awardTitle(strategyAward.getAwardTitle())
                .sort(strategyAward.getSort())
                .build();
    }

    /**
     * 抽奖计算，责任链抽象方法
     * @param userId
     * @param strategyId
     * @return
     */
    public abstract DefaultChainFactory.StrategyAwardVo raffleLogicChain(String userId,Long strategyId);

    /**
     * 抽奖计算，决策树抽象方法
     * @param userId
     * @param strategyId
     * @param awardId
     * @return
     */
    public abstract DefaultTreeFactory.StrategyAwardVo raffleLogicTree(String userId, Long strategyId, Integer awardId);

//    protected abstract RuleActionEntity<RuleActionEntity.RaffleBeforeEntity> doCheckRaffleBeforeLogic(RaffleFactorEntity raffleFactorEntity, String... logics);
//    protected abstract RuleActionEntity<RuleActionEntity.RaffleCenterEntity> doCheckRaffleCenterLogic(RaffleFactorEntity raffleFactorEntity, String... logics);
}
